package com.mall.common.util;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * Nacos工具类
 * 提供Nacos配置中心的常用操作方法
 * 
 * 默认情况下，所有操作都使用应用配置的命名空间。
 * 可通过指定namespace参数的方法操作其他命名空间中的配置。
 */
@Slf4j
@Component
public class NacosUtil {

    @Autowired
    private NacosConfigManager nacosConfigManager;

    /**
     * 发布配置
     * 默认使用应用配置的命名空间
     *
     * @param dataId  配置ID
     * @param group   配置分组
     * @param content 配置内容
     * @return 是否成功
     */
    public boolean publishConfig(String dataId, String group, String content) {
        try {
            return nacosConfigManager.getConfigService().publishConfig(dataId, group, content);
        } catch (Exception e) {
            log.error("发布配置失败, dataId: {}, group: {}", dataId, group, e);
            return false;
        }
    }

    /**
     * 发布配置（指定命名空间）
     *
     * @param dataId    配置ID
     * @param group     配置分组
     * @param content   配置内容
     * @param namespace 命名空间
     * @return 是否成功
     */
    public boolean publishConfig(String dataId, String group, String content, String namespace) {
        try {
            ConfigService configService = nacosConfigManager.getConfigService();
            // 通过反射获取ConfigService的publishConfig方法，支持命名空间参数
            java.lang.reflect.Method method = configService.getClass().getDeclaredMethod(
                    "publishConfig", String.class, String.class, String.class, String.class);
            method.setAccessible(true);
            return (Boolean) method.invoke(configService, dataId, group, content, namespace);
        } catch (Exception e) {
            log.error("发布配置失败, dataId: {}, group: {}, namespace: {}", dataId, group, namespace, e);
            return false;
        }
    }

    /**
     * 获取配置
     * 默认使用应用配置的命名空间
     *
     * @param dataId 配置ID
     * @param group  配置分组
     * @return 配置内容
     */
    public String getConfig(String dataId, String group) {
        try {
            return nacosConfigManager.getConfigService().getConfig(dataId, group, 3000);
        } catch (Exception e) {
            log.error("获取配置失败, dataId: {}, group: {}", dataId, group, e);
            return null;
        }
    }

    /**
     * 获取配置（指定命名空间）
     *
     * @param dataId    配置ID
     * @param group     配置分组
     * @param namespace 命名空间
     * @return 配置内容
     */
    public String getConfig(String dataId, String group, String namespace) {
        try {
            ConfigService configService = nacosConfigManager.getConfigService();
            // 通过反射获取ConfigService的getConfig方法，支持命名空间参数
            java.lang.reflect.Method method = configService.getClass().getDeclaredMethod(
                    "getConfig", String.class, String.class, String.class, long.class);
            method.setAccessible(true);
            return (String) method.invoke(configService, dataId, group, namespace, 3000L);
        } catch (Exception e) {
            log.error("获取配置失败, dataId: {}, group: {}, namespace: {}", dataId, group, namespace, e);
            return null;
        }
    }

    /**
     * 删除配置
     * 默认使用应用配置的命名空间
     *
     * @param dataId 配置ID
     * @param group  配置分组
     * @return 是否成功
     */
    public boolean removeConfig(String dataId, String group) {
        try {
            return nacosConfigManager.getConfigService().removeConfig(dataId, group);
        } catch (Exception e) {
            log.error("删除配置失败, dataId: {}, group: {}", dataId, group, e);
            return false;
        }
    }

    /**
     * 删除配置（指定命名空间）
     *
     * @param dataId    配置ID
     * @param group     配置分组
     * @param namespace 命名空间
     * @return 是否成功
     */
    public boolean removeConfig(String dataId, String group, String namespace) {
        try {
            ConfigService configService = nacosConfigManager.getConfigService();
            // 通过反射获取ConfigService的removeConfig方法，支持命名空间参数
            java.lang.reflect.Method method = configService.getClass().getDeclaredMethod(
                    "removeConfig", String.class, String.class, String.class);
            method.setAccessible(true);
            return (Boolean) method.invoke(configService, dataId, group, namespace);
        } catch (Exception e) {
            log.error("删除配置失败, dataId: {}, group: {}, namespace: {}", dataId, group, namespace, e);
            return false;
        }
    }

    /**
     * 添加监听器
     * 默认使用应用配置的命名空间
     *
     * @param dataId   配置ID
     * @param group    配置分组
     * @param listener 监听器
     */
    public void addListener(String dataId, String group, Listener listener) {
        try {
            nacosConfigManager.getConfigService().addListener(dataId, group, listener);
        } catch (Exception e) {
            log.error("添加监听器失败, dataId: {}, group: {}", dataId, group, e);
        }
    }

    /**
     * 添加监听器（指定命名空间）
     *
     * @param dataId    配置ID
     * @param group     配置分组
     * @param namespace 命名空间
     * @param listener  监听器
     */
    public void addListener(String dataId, String group, String namespace, Listener listener) {
        try {
            ConfigService configService = nacosConfigManager.getConfigService();
            // 通过反射获取ConfigService的addListener方法，支持命名空间参数
            java.lang.reflect.Method method = configService.getClass().getDeclaredMethod(
                    "addListener", String.class, String.class, String.class, Listener.class);
            method.setAccessible(true);
            method.invoke(configService, dataId, group, namespace, listener);
        } catch (Exception e) {
            log.error("添加监听器失败, dataId: {}, group: {}, namespace: {}", dataId, group, namespace, e);
        }
    }

    /**
     * 添加监听器（简化版本）
     * 默认使用应用配置的命名空间
     *
     * @param dataId   配置ID
     * @param group    配置分组
     * @param callback 回调函数
     */
    public void addListener(String dataId, String group, Runnable callback) {
        try {
            nacosConfigManager.getConfigService().addListener(dataId, group, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    callback.run();
                }
            });
        } catch (Exception e) {
            log.error("添加监听器失败, dataId: {}, group: {}", dataId, group, e);
        }
    }

    /**
     * 添加监听器（简化版本，指定命名空间）
     *
     * @param dataId    配置ID
     * @param group     配置分组
     * @param namespace 命名空间
     * @param callback  回调函数
     */
    public void addListener(String dataId, String group, String namespace, Runnable callback) {
        try {
            ConfigService configService = nacosConfigManager.getConfigService();
            Listener listener = new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    callback.run();
                }
            };
            // 通过反射获取ConfigService的addListener方法，支持命名空间参数
            java.lang.reflect.Method method = configService.getClass().getDeclaredMethod(
                    "addListener", String.class, String.class, String.class, Listener.class);
            method.setAccessible(true);
            method.invoke(configService, dataId, group, namespace, listener);
        } catch (Exception e) {
            log.error("添加监听器失败, dataId: {}, group: {}, namespace: {}", dataId, group, namespace, e);
        }
    }
}